package cz.cvut.fel.y36mm1.videostreaming.devicediscovery;

import cz.cvut.fel.y36mm1.videostreaming.MainMidlet;
import java.io.IOException;
import java.util.Hashtable;
import javax.bluetooth.BluetoothStateException;
import javax.bluetooth.DeviceClass;
import javax.bluetooth.DiscoveryAgent;
import javax.bluetooth.DiscoveryListener;
import javax.bluetooth.LocalDevice;
import javax.bluetooth.RemoteDevice;
import javax.bluetooth.ServiceRecord;
import javax.bluetooth.UUID;

/**
 * Trida zprostredkovava vyhledavani Bluetooth zarizeni v okoli.
 *
 * @author Jiri Masek, masekj5
 */
public class DeviceDiscoverer implements DiscoveryListener {

    private static DeviceDiscoverer instance;
	/**
	 * table with discovered devices &lt;device name, service url&gt;
	 */
    private Hashtable devices;
    private LocalDevice localDevice;
    private DiscoveryAgent discoveryAgent;
    private DevicesScreen devicesScreen;
    private UUID[] uuidSet;
    private String serviceUrl;
    private String deviceName;

    private DeviceDiscoverer() {
        devicesScreen = new DevicesScreen("Found devices");
        devices = new Hashtable();

        try {
            localDevice = LocalDevice.getLocalDevice();
        } catch (BluetoothStateException ex) {
            System.err.println("BluetoothStateException: " + ex.getMessage());
        }

        discoveryAgent = localDevice.getDiscoveryAgent();
    }

    /**
     * Vrati instanci tridy <code>DeviceDiscoverer</code>
     *
     * @return  instanci tridy <code>DeviceDiscoverer</code>
     */
    public static DeviceDiscoverer getInstance() {
        if (instance == null) {
            instance = new DeviceDiscoverer();
        }
        return instance;
    }

    /**
     * Zahaji vyhledavani Bluetooth zarizeni v okoli.
     *
     * @throws javax.bluetooth.BluetoothStateException
     */
    public void startInquiry() throws BluetoothStateException {
        devices.clear();

        discoveryAgent.startInquiry(DiscoveryAgent.GIAC, this);
    }

    /**
     * Metoda volana pri nalezeni Bluetooth zarizeni.
     *
     * @param btDevice      Bluetooth zarizeni
     * @param cod           trida zarizeni
     */
    public void deviceDiscovered(RemoteDevice btDevice, DeviceClass cod) {
        try {
            deviceName = btDevice.getFriendlyName(true);

            // Search for Services
            uuidSet = new UUID[1];
            uuidSet[0] = MainMidlet.RFCOMM_UUID;

            discoveryAgent.searchServices(null, uuidSet, btDevice, this);
        } catch (IOException ex) {
            System.err.println("IOException: " + ex.getMessage());
        }
    }

    /**
     * Metoda volana pri nalezeni sluzby na Bluetooth zarizeni.
     *
     * @param transID
     * @param servRecord
     */
    public void servicesDiscovered(int transID, ServiceRecord[] servRecord) {
        for (int i = 0; i < servRecord.length; i++) {
            serviceUrl = servRecord[i].getConnectionURL(0, false);
        }
    }

    /**
     * Metoda volana pri dokonceni vyhledavani sluzeb na Bluetooth zarizeni.
     *
     * @param transID
     * @param responseCode
     */
    public void serviceSearchCompleted(int transID, int responseCode) {
        if (responseCode == SERVICE_SEARCH_ERROR) {
        }

        if (responseCode == SERVICE_SEARCH_COMPLETED) {
            devices.put(deviceName, serviceUrl);
            devicesScreen.newDeviceDiscovered(deviceName);
        }

        if (responseCode == SERVICE_SEARCH_TERMINATED) {
        }

        if (responseCode == SERVICE_SEARCH_NO_RECORDS) {
        }

        if (responseCode == SERVICE_SEARCH_DEVICE_NOT_REACHABLE) {
        }
    }

    /**
     * Metoda volani pri dokonceni vyhledavani Bluetooth zarizeni.
     *
     * @param discType
     */
    public void inquiryCompleted(int discType) {
        /*if (!devices.isEmpty()) {
            devicesScreen.addInquiryCompletedNote();
        } else {
            devicesScreen.noServerAvailable();
        }*/
		 devicesScreen.addInquiryCompletedNote();
    }

    /**
     * 
     * @return
     */
    public DevicesScreen getDevicesScreen() {
        return devicesScreen;
    }

    /**
     * Vrati tabulku nalezenych Bluetooth zarizeni.
     *
     * @return      tabulka Bluetooth zarizeni
     */
    public Hashtable getDevices() {
        return devices;
    }
}